package com.zqxq.auth.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zqxq.auth.cache.UserFuncCache;
import com.zqxq.auth.entity.po.Func;
import com.zqxq.auth.entity.bo.UserFuncBO;
import com.zqxq.auth.entity.module.Code;
import com.zqxq.auth.entity.module.Result;
import com.zqxq.auth.config.ResponseWrapper;
import com.zqxq.auth.config.WebFilterConfiguration;
import com.zqxq.auth.tools.WebUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 何三七 on 2018/01/11 14:01
 */
public class AuthFilter implements Filter {

    private UserFuncCache userFuncCache;
    private boolean skip_swagger;

    private HashMap<Integer,HashMap<String, Integer>> dataDesensitization;//脱敏参数map,服务器启动时,添加数据，其他均为查询

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");//解决跨域
        String requestUri = httpServletRequest.getRequestURI();
        String token_id = httpServletRequest.getParameter("token_id");
//        chain.doFilter(httpServletRequest, httpServletResponse);
        //判断swagger 是否直接放过
        if (isSkipSwagger(requestUri, httpServletRequest)) {
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        //判断是否图片，图片直接放过
        if(isImage(requestUri)){
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        boolean isLogin = userFuncCache.validLogin(token_id);//验证登录、设置有效时间
        //不用登录即可访问功能
        Func func = userFuncCache.getNoLoginAccessibleInfo(requestUri);
        if (func != null) {
            userFuncCache.saveAccessLog(httpServletRequest, func);//保存访问日志
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        //验证用户是否登录
        if (!isLogin) {
            Result result = new Result(Code.NO_LOGIN, "请登录");
            WebUtils.outPrint(httpServletResponse, JSON.toJSONString(result));
            return;
        }

        //验证ip，是否为登录ip
        /*if (!userFuncCache.validLoginIp(httpServletRequest, token_id)) {
            Result result = new Result(Code.NO_LOGIN, "请登录");
            WebUtils.outPrint(httpServletResponse, JSON.toJSONString(result));
            return;
        }*/

        //登录即可访问功能
        func = userFuncCache.getLoginAccessibleInfo(requestUri);
        if (func != null) {
            userFuncCache.saveAccessLog(httpServletRequest, func);//保存访问日志
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        UserFuncBO userFuncBO = userFuncCache.getUserOwnFunc(token_id, requestUri);
        //判断用户是否有权限访问
        if (userFuncBO == null) {
            Result result = new Result(Code.NO_AUTH, "无访问权限");
            WebUtils.outPrint(httpServletResponse, JSON.toJSONString(result));
            return;
        }

        userFuncCache.saveAccessLogBO(httpServletRequest, userFuncBO);
        wrapper(httpServletRequest, httpServletResponse, chain, userFuncBO);
//        return;



    }

    /**
     * 判断是否图片链接，判断后缀是否png，jpg,jpeg,gif,bmp
     * @param uri
     * @return
     */
    private  boolean isImage(String uri){
        if(StringUtils.isNotBlank(uri)){
            if(uri.endsWith("png") || uri.endsWith("jpg") || uri.endsWith("jpeg") || uri.endsWith("gif") || uri.endsWith("bmp")){
                return true;
            }
        }
        return false;
    }
    private void wrapper(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain chain, UserFuncBO userFuncBO) throws IOException, ServletException {
        if (isDesen(userFuncBO)) {
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        HashMap<String, Integer> keyMap = getDesenMap(userFuncBO);
        if (keyMap.isEmpty()) {
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse);
        chain.doFilter(httpServletRequest, responseWrapper);
        byte[] content = responseWrapper.getContent();//获取返回值
        if (content.length > 0) {
            String str = new String(content, "UTF-8");
//            System.out.println("========返回值====:" + str);
            JSONObject obj = JSONObject.parseObject(str);
            Object data = obj.get("data");
            if (data != null) {
                Object b = parse(obj, keyMap);
                str = JSONObject.toJSONString(b);
//                System.out.println("========修改后数据:::::::::::::：" + str);
            }
            httpServletResponse.setContentLength(-1);
            WebUtils.outPrint(httpServletResponse, str);
        } else {
            System.out.println("我是空。。。。。。。。。。。。。。");
        }
    }
    private HashMap<String, Integer> getDesenMap(UserFuncBO userFuncBO) {
        HashMap<String, Integer> keyMap = new HashMap<>();
        if (userFuncBO.getPhone_auth() == 0) {//屏蔽手机号
            keyMap.putAll(dataDesensitization.get(WebFilterConfiguration.PHONE));
        }
        if (userFuncBO.getId_no_auth() == 0) {
            keyMap.putAll(dataDesensitization.get(WebFilterConfiguration.ID_NO));
        }
        if (userFuncBO.getBank_auth() == 0) {
            keyMap.putAll(dataDesensitization.get(WebFilterConfiguration.BANK));
        }
        return keyMap;
    }

    /**
     * 下载、未设置脱敏字段、所有字段均可查看用户，不进行脱敏
     * @param userFuncBO
     * @return
     */
    private boolean isDesen(UserFuncBO userFuncBO) {
        if (userFuncBO.getDownload_flag() == 1 || dataDesensitization.isEmpty()) {
            return true;
        }
        if (userFuncBO.getPhone_auth() == 1 && userFuncBO.getId_no_auth() == 1 && userFuncBO.getBank_auth() == 1) {
            return true;
        }
        return false;
    }

    private Object parse(Object obj, Map<String, Integer> keyMap) {
        if (obj == null) return obj;
        if (obj instanceof Map) {
            JSONObject jsonObject = (JSONObject) obj;
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                Object value = entry.getValue();
                if (value == null) continue;
                String key = entry.getKey();
                Integer type = keyMap.get(key);
                if (type != null) {
                    String dataStr = (String) value;
                    if (dataStr.indexOf("*") != -1) {//如果有*, 则不处理
                        continue;
                    }
                    this.handleValueStar(jsonObject, dataStr, type, key);

                } else {
                    jsonObject.put(key, parse(value, keyMap));
                }
            }
        } else if (obj instanceof List) {
            JSONArray jsonArray = (JSONArray) obj;
            for(Object o : jsonArray) {
                parse(o, keyMap);
            }
        }
        return obj;
    }


    private void handleValueStar(JSONObject jsonObject, String dataStr, Integer type, String key) {
        int len = dataStr.length();
        if (type == WebFilterConfiguration.PHONE) {
            if (len > 7) {//前3后4
                dataStr = dataStr.substring(0,3) + getStart(len - 7) + dataStr.substring(len - 4, len);
            }
        } else if (type == WebFilterConfiguration.ID_NO) {
            if (len > 10) {//前6后4
                dataStr = dataStr.substring(0,6) + getStart(len - 10) + dataStr.substring(len - 4, len);
            }
        } else if (type == WebFilterConfiguration.BANK) {
            if (len > 10) {//前6后4
                dataStr = dataStr.substring(0,6) + getStart(len - 10) + dataStr.substring(len - 4, len);
            }
        }
        jsonObject.put(key, dataStr);
    }

    private String getStart(int num) {
        String re = "";
        for(int i=0; i<num; i++) {
            re += "*";
        }
        return re;
    }
    /**
     * 是否跳过swagger，不拦截
     * @param requestUri
     * @param httpServletRequest
     * @return
     */
    private boolean isSkipSwagger(String requestUri, HttpServletRequest httpServletRequest) {
        if (skip_swagger) {//如果配置不拦截 swagger ，则执行下面方法
            if (requestUri.indexOf("swagger") != -1 || requestUri.indexOf("/v2/") != -1) {
                return true;
            }
            String referer = httpServletRequest.getHeader("referer");
            if (referer != null && referer.indexOf("swagger") != -1) {
                return true;
            }
        }
        return false;
    }
    @Override
    public void destroy() {

    }

    public UserFuncCache getUserFuncCache() {
        return userFuncCache;
    }

    public void setUserFuncCache(UserFuncCache userFuncCache) {
        this.userFuncCache = userFuncCache;
    }

    public boolean isSkip_swagger() {
        return skip_swagger;
    }

    public void setSkip_swagger(boolean skip_swagger) {
        this.skip_swagger = skip_swagger;
    }

    public HashMap<Integer, HashMap<String, Integer>> getDataDesensitization() {
        return dataDesensitization;
    }

    public void setDataDesensitization(HashMap<Integer, HashMap<String, Integer>> dataDesensitization) {
        this.dataDesensitization = dataDesensitization;
    }
}
